LeetCode-50-Pow(x, n)
in LeetCode with 0 comment

LeetCode-50-Pow(x, n)

in LeetCode with 0 comment

原题地址:Pow(x, n)

实现 $pow(x, n)$ ,即计算 x 的 n 次幂函数。

示例 1:

输入: 2.00000, 10
输出: 1024.00000

示例 2:

输入: 2.10000, 3
输出: 9.26100

示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:

连乘

按幂的计算规则,将x连乘n次即可,注意处理n为负的情况:

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
const myPow1 = function(x, n) {
    // x^n = (1/x)^(-n),统一将n转为正数计算
    if (n < 0) {
        x = 1 / x;
        n = -n;
    }
    // 依次累乘即可
    let result = 1;
    for (let i = 0; i < n; i ++) {
        result *= x;
    }
    return result;
};

测试:

let start = new Date();
const test = myPow1;
console.log(test(2.00000, 10)); // 1024
console.log(test(2.10000, 3)); // 9.261000000000001
console.log(test(2.00000, -2)); // 0.25
console.log(new Date().getTime() - start.getTime()); // 8

时间复杂度: 连乘n次,时间复杂度为$O(N)$,其中N为绝对值,当N过大时,会超时
空间复杂度: 空间复杂度为$O(1)$

二分优化

利用$x^{2i}=x^i \times x^i$,我们可以将连乘优化,时间复杂度降为$O(logN)$:

/**
 * 递归计算幂
 * @param x 乘数
 * @param n 幂
 * @returns {number} pow(x,n)
 */
const fastPow = (x, n) => {
    // 任何数的0次方都等于1
    if (n === 0) {
        return 1;
    }
    // 计算 x^(n/2)
    let fast = fastPow(x, Math.floor(n / 2));
    if ( n % 2 === 0) {
        // 如果n为偶数,那么x^n = x^(n/2) * x^(n/2)
        return fast * fast;
    } else {
        // 如果x为奇数,额外乘上x即可
        return fast * fast * x;
    }
};

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
const myPow2 = function(x, n) {
    // x^n = (1/x)^(-n),统一将n转为正数计算
    if (n < 0) {
        x = 1 / x;
        n = -n;
    }
    return fastPow(x, n);
};

测试:

let start = new Date();
const test = myPow1;
console.log(test(2.00000, 10)); // 1024
console.log(test(2.10000, 3)); // 9.261000000000001
console.log(test(2.00000, -2)); // 0.25
console.log(new Date().getTime() - start.getTime()); // 7

时间复杂度: 时间复杂度为$O(logN)$
空间复杂度: 每一次计算结果都需要保存,直到得出最终结果,空间复杂度为$O(logN)$